﻿//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace Microsoft.Ted.Wacel
{
    [DataContract]
    public class Dimension: DimensionNode
    {
        public Dimension(string name):base(name, null, DimensionNodeType.DimensionRoot)
        {
            Name = name;
            Children = new List<DimensionNode>();
        }

        [DataMember]
        public DimensionNodeType LeafNodeType { get; set; } //TODO: Auto maintain this.
        [DataMember]
        public DimensionType DimensionType { get; set; } 
        public static Dimension GetTimeDimensionMonthDays(int year)
        {
            Dimension ret = new Dimension("Time") { DimensionType = DimensionType.Time };
            ret.Children.Add(new DimensionNode(year.ToString(), ret, DimensionNodeType.DateTimeYear));
            var yearNode = ret.Children[0];
            string[] months = new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
            int[] days = new int[] { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
            for (int i = 0; i < months.Length; i++)
            {
                DimensionNode monthNode = new DimensionNode(months[i], ret, DimensionNodeType.DateTimeMonth);
                for (int j = 1; j <= days[i]; j++)
                {
                    DimensionNode dayNode = new DimensionNode(months[i] + j.ToString(), ret, DimensionNodeType.DateTimeDay);
                    dayNode.Parent = monthNode;
                    monthNode.Children.Add(dayNode);
                }
                monthNode.Parent = yearNode;
                yearNode.Children.Add(monthNode);
            }
            ret.LeafNodeType = DimensionNodeType.DateTimeDay;
            return ret;
        }

        public  string GetTimeDimensionKey(DateTime date)
        {
            string[] months = new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
            switch (LeafNodeType)
            {
                case DimensionNodeType.DateTimeDay:
                    return months[date.Month - 1] + date.Day;
                case DimensionNodeType.DateTimeHour:
                    return months[date.Month - 1] + date.Day + "_" + date.Hour;
                case DimensionNodeType.DateTime5Minute:
                    return months[date.Month - 1] + date.Day + "_" + date.Hour + "_" + date.Minute / 5 * 5;
                default:
                    throw new NotSupportedException("GetTimeDimensionKey can be invoked only on Time dimension.");
            }
        }

        private static string[] MonthNames = new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
        public static string Get5MinuteTimeKey(DateTime date)
        {
            return MonthNames[date.Month - 1] + date.Day + "_" + date.Hour + "_" + date.Minute / 5 * 5;
        }
        public static string GetHourTimeKey(DateTime date)
        {
            return MonthNames[date.Month - 1] + date.Day + "_" + date.Hour;
        }
        public static string GetDayTimeKey(DateTime date)
        {
            return MonthNames[date.Month - 1] + date.Day;
        }
        public static Dimension GetTimeDimensionMonthDayHours(int year)
        {
            Dimension ret = GetTimeDimensionMonthDays(year);
            var months = ret.Children[0].Children;
            foreach(var month in months)
            {
                foreach (var dayNode in month.Children)
                {
                    for (int i = 0; i < 24; i++)
                    {
                        DimensionNode hourNode = new DimensionNode(dayNode.Name + "_" + i.ToString(), ret, DimensionNodeType.DateTimeHour);
                        hourNode.Parent = dayNode;
                        dayNode.Children.Add(hourNode);
                    }
                }
            }
            ret.LeafNodeType = DimensionNodeType.DateTimeHour;
            return ret;
        }
        public static Dimension GetTimeDimensionMonthDayHour5Minutes(int year)
        {
            Dimension ret = GetTimeDimensionMonthDayHours(year);
            var months = ret.Children[0].Children;
            foreach (var month in months)
            {
                foreach (var dayNode in month.Children)
                {
                    foreach (var hourNode in dayNode.Children)
                    {
                        for (int i = 0; i < 12; i++)
                        {
                            DimensionNode minuteNode = new DimensionNode(hourNode.Name + "_" + (i*5).ToString(), ret, DimensionNodeType.DateTime5Minute);
                            minuteNode.Parent = hourNode;
                            hourNode.Children.Add(minuteNode);
                        }
                    }
                }
            }
            ret.LeafNodeType = DimensionNodeType.DateTime5Minute;
            return ret;
        }
        public static Dimension CreateFlatDimension(string name, params string[] nodes)
        {
            Dimension ret = new Dimension(name) { DimensionType = DimensionType.Flat };
            foreach (var node in nodes)
                ret.Children.Add(new DimensionNode(node, ret, DimensionNodeType.Independant));
            return ret;
        }
        public static Dimension CreateFreeDimension(string name)
        {
            Dimension ret = new Dimension(name) { DimensionType = DimensionType.Free };
            return ret;
        }
    }
}
